﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Google.GData.Client;
using System.Net;

namespace MyPublish.Connection.Syndication.Blogger
{
    [DataConnectionProvider(Name = "Blogger", Type = typeof(BloggerConnectionProvider))]
    public class BloggerConnectionProvider : DataConnectionProvider
    {
        public const string BLOGGER_URI = "http://beta.blogger.com/feeds/default/blogs";

        private Service _gService;
        public Service GService
        {
            get
            {
                if (_gService == null)
                {
                    _gService = new Service("blogger", "MyPublish.Connection.Syndication");
                    GService.Credentials =
                        new GDataCredentials(ConnectionString.UserName, ConnectionString.Password);
                    GDataRequestFactory requestFactory = (GDataRequestFactory)GService.RequestFactory;
                    requestFactory.KeepAlive = true;
                    if (Proxy != null)
                    {
                        GDataRequestFactory requestFactory2 = (GDataRequestFactory)_gService.RequestFactory;
                        requestFactory2.Proxy = Proxy;
                    }
                }

                return _gService;
            }
        }

        public BloggerConnectionProvider() { }
        public BloggerConnectionProvider(DataConnectionString connectionString)
            : base(connectionString)
        {
        }

        public BloggerConnectionProvider(DataConnectionString connString, WebProxy proxy)
            : base(connString, proxy)
        {
        }

        public override IEnumerable<object> ExecuteQuery()
        {
            List<object> settingList = new List<object>();

            Stack<string> feedUris = new Stack<string>();
            feedUris.Push(BLOGGER_URI);

            while (feedUris.Count != 0)
            {
                string uriString = feedUris.Pop();
                AtomFeed feed = null;
                try
                {
                    FeedQuery feedQuery = new FeedQuery()
                    {
                        Uri = new Uri(uriString)
                    };
                    feed = GService.Query(feedQuery);
                    if (feed == null || feed.Entries.Count <= 0)
                        continue;

                    foreach (AtomEntry entry in feed.Entries)
                    {
                        BlogData setting = new BlogData();
                        setting.Title = entry.Title.Text;
                        setting.UserName = ConnectionString.UserName;
                        foreach (AtomLink link in entry.Links)
                        {
                            if (link.Rel == "http://schemas.google.com/g/2005#feed")
                            {
                                setting.FeedURL = link.HRef.ToString();
                            }
                            else if (link.Rel == "http://schemas.google.com/g/2005#post")
                            {
                                setting.PostURL = link.HRef.ToString();
                            }
                            else if (link.Rel == "self")
                            {
                                setting.SelfFeedURL = link.HRef.ToString();
                                if ((((setting.SelfFeedURL.LastIndexOf("/") > 0) && ((setting.SelfFeedURL.LastIndexOf("/") + 1) < setting.SelfFeedURL.Length)) ? 1 : 0) != 0)
                                {
                                    setting.ID = setting.SelfFeedURL.Substring(setting.SelfFeedURL.LastIndexOf("/") + 1);
                                }
                            }
                            else if (link.Rel == "alternate")
                            {
                                setting.BlogURL = link.HRef.ToString();
                            }
                        }

                        settingList.Add(setting);
                    }

                    if (!string.IsNullOrEmpty(feed.NextChunk))
                    {
                        feedUris.Push(feed.NextChunk);
                    }
                }
                catch (Exception e)
                {
                    if (feed == null)
                    {
                        throw new DataConnectionException("Failed to query feeds." + e.Message, e);
                    }
                }
            }

            return settingList;
        }

        public override IEnumerable<object> ExecuteQuery(object data)
        {
            BlogData blog = data as BlogData;

            List<object> items = new List<object>();
            AtomFeed feed = null;
            try
            {
                FeedQuery feedQuery = new FeedQuery()
                {
                    Uri = new Uri(blog.Url)
                };
                feed = GService.Query(feedQuery);
                if (feed == null || feed.Entries.Count <= 0)
                {
                    return items;
                }

                foreach (AtomEntry entry in feed.Entries)
                {
                    PostData item = new PostData()
                    {
                        Title = new PostText()
                        {
                            Text = entry.Title.Text,
                            Type = (PostTextType)(int)entry.Title.Type
                        },
                        Published = entry.Published,
                        Content = new PostContent()
                        {
                            Type = entry.Content.Type,
                            Content = entry.Content.Content
                        },
                        Link = new Uri(entry.Links[0].AbsoluteUri)
                    };
                    items.Add(item);
                }
            }
            catch (Exception e)
            {
                if (feed == null)
                {
                    throw new DataConnectionException("Failed to query feeds." + e.Message, e);
                }
            }

            return items;
        }
    }
}
